Apache DoS攻撃にそなえる
mod_evasiveをインストールする
ApacheのDoS攻撃対策で有名なところとしてmod_evasiveやmod_dosdetectorが有名どころですね。 今回はmod_evasiveをインストール&セットアップしてみます。 セットアップ環境はお決まりのAWS Amazon Linuxです。早速ソースをダウンロードしてきて、セットアップします。 事前にApacheモジュール(mod_so.c)が有効かを確認します。
# /usr/local/apache2/bin/apachectl -l Compiled in modules: core.c ・ ・ 多いので省略(そもそも多いのも改善の余地はありますがw) ・ mod_env.c mod_setenvif.c mod_version.c prefork.c http_core.c mod_alias.c mod_so.c
mod_so.cが有効になっているので、次に進みます。(これが入ってない方はhttpd-develを先にインストールする必要があります。) mod_evasiveはhttp://www.zdziarski.com/でダウンロードできます。
# cd /usr/local/src/ # wget http://www.zdziarski.com/blog/wp-content/uploads/2010/02/mod_evasive_1.10.1.tar.gz # tar zxvf mod_evasive_1.10.1.tar.gz # cd mod_evasive # /usr/local/apache2/bin/apxs -i -a -c mod_evasive20.c # cd /usr/local/apache2/modules # ls -l mod_evasive20.so -rwxr-xr-x 1 root root 51287 Mar 1 15:33 mod_evasive20.so
必要に応じてmod_evasive20.cを編集して、通知メールの設定を行うこともできますが、今はデフォルトのままでセットアップを進めます。
mod_evasiveの設定
ログ書き出しディレクトリを作成します。(apacheを実行しているユーザにオーナーを変更しておきます。)
# mkdir /var/log/mod_evasive/ # chown apache:apache /var/log/mod_evasive/
次にapacheのコンフィグレーションファイルを開いてDos攻撃とみなす条件を設定します。 自動でLoadModule evasive20_module modules/mod_evasive20.soが追加されていると思いますので確認します。あとはIfModuleを追加してhttpd.confに設定反映させます。(デフォルト値はmod_evasive20.cをviで開くと記載があります。)以下がデフォルト値のようです。
#define DEFAULT_HASH_TBL_SIZE 3097ul // Default hash table size #define DEFAULT_PAGE_COUNT 2 // Default maximum page hit count per interval #define DEFAULT_SITE_COUNT 50 // Default maximum site hit count per interval #define DEFAULT_PAGE_INTERVAL 1 // Default 1 Second page interval #define DEFAULT_SITE_INTERVAL 1 // Default 1 Second site interval #define DEFAULT_BLOCKING_PERIOD 10 // Default for Detected IPs; blocked for 10 seconds #define DEFAULT_LOG_DIR "/tmp" // Default temp directory
下記設定は同一ページに2秒間で3回のリクエストがあった場合と同一サイトに1秒間に20回アクセスがあった場合に3600秒アクセス禁止(403 Forbidden)にする設定です。ちょっと長めに設定しすぎかな^^; この値は必要に応じてチューニングする必要があります。
# cd /usr/local/apache2/conf # vi httpd.conf LoadModule evasive20_module modules/mod_evasive20.so <IfModule mod_evasive20.c> DOSHashTableSize 3097 DOSPageCount 3 DOSSiteCount 20 DOSPageInterval 2 DOSSiteInterval 1 DOSBlockingPeriod 3600 DOSLogDir "/var/log/mod_evasive" DOSEmailNotify xxxxx@xxxx.jp ←拒否したIPアドレスをメール送付。 </IfModule>
設定が完了したらviを終了して、Apacheの再起動を行います。
# service httpd restart # /usr/local/apache2/bin/apachectl -M Loaded Modules: core_module (static) authn_file_module (static) authn_default_module (static) authz_host_module (static) authz_groupfile_module (static) authz_user_module (static) authz_default_module (static) auth_basic_module (static) ・ ・ ・ so_module (static) evasive20_module (shared) proxy_module (shared) proxy_http_module (shared) Syntax OK
evasive20_moduleが読み込まれていることを一応確認
動作テスト
検証用のPerlモジュールが入っているので、それを実行して動作確認をします。実行権が付いてない場合は実行権を付与します。
# cd /usr/local/src/mod_evasive # chmod +x test.pl # /usr/local/src/mod_evasive/test.pl HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 200 OK HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden
途中から403 Forbiddenになり拒否されたことが確認できました。ログは拒否したIP単位で残ります。
# cd /var/log/mod_evasive # ls -l -rw-r--r-- 1 apache apache 5 Mar 6 13:35 dos-127.0.0.1 # cd .. # grep Blacklisting messages Mar 6 13:35:57 ip-10-156-205-80 mod_evasive[1612]: Blacklisting address 127.0.0.1: possible DoS attack.
正しく動作していることが確認できたので、ループバック・アドレスは対象外にするように設定ファイルを変更します。
# cd /usr/local/apache2/conf # vi httpd.conf LoadModule evasive20_module modules/mod_evasive20.so <IfModule mod_evasive20.c> DOSHashTableSize 3097 DOSPageCount 3 DOSSiteCount 20 DOSPageInterval 2 DOSSiteInterval 1 DOSBlockingPeriod 3600 DOSLogDir "/var/log/mod_evasive" DOSWhitelist 127.0.0.1 ←ループバック・アドレスをホワイトリストにする設定。 DOSEmailNotify xxxxx@xxxx.jp </IfModule> # service httpd restart
次に外部からアクセスして正しく拒否するかをテストしてみます 別のEC2インスタンスにSSHでログインして下記コマンドを実行してみます。(Apacheはソースからインストールされているものを利用しています。)
# /usr/local/apache2/bin/ab -n 50 -c 10 http://xxx.xxx.xxx.xxx/index.html(xxx.xxx.xxx.xxxはmod_evasiveの入っているサーバです)
別インスタンスからapacheのabコマンドを実行する前にmod_evasiveの入ってるサーバで以下を実行してログ監視しておく
# tail -f /var/log/messages Mar 6 14:09:38 ip-10-156-205-80 mod_evasive[1678]: Blacklisting address xxx.xxx.xxx.xxx: possible DoS attack.
ちゃんとxxx.xxx.xxx.xxxのIPアドレスからのリクエストをブロックしたことが確認できました。/var/log/mod_evasive/配下にも拒否したIP単位で残っていました。しばらく運用してみて設定値のブロック条件の調整をしようと思います。